import java.io.*;

public class PlainTextAttack {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws FileNotFoundException, IOException  {
		LargeKey lKey = new LargeKey();
		FirstScan first = new FirstScan();
		Stock st = new Stock();
		boolean DoFourth = false;
		
		int BlockSize = 8128;
		
		System.out.println("Starting Attack");
		long startTime = System.currentTimeMillis();
		
		System.out.println("Starting Phase 1 - Plaintext");
		//lKey = first.CKnown(args[2], args[0], args[3], BlockSize);
		System.out.println("Matches found:");
		System.out.println(lKey);
		System.out.println("Phase 1 Done");
		System.out.println(lKey.CountMissingValues() + " missing values");
		
		if (!lKey.isFullyMapped()){
			System.out.println("Decrypting");
			st.Transform(args[1],args[0], lKey, BlockSize);
			System.out.println("Starting Phase 2 - Dictionary");
			lKey = SecondScan.Scan(lKey, args[0], args[1], BlockSize);
			System.out.println("Phase 2 Done");
			System.out.println("Confidence Level: " + SecondScan.confidence);
			System.out.println(lKey.CountMissingValues() + " missing values");
			
			System.out.println(lKey);
			
			if (!lKey.isFullyMapped()){
				int i, j;
				if (lKey.CountMissingValues()<=6 && lKey.CountMissingValues()!=1){
					System.out.println("Starting Phase 3 - Bruteforce");
					
					byte [] iv = SecondScan.OpenFile(args[0]);
			        byte [] cb = SecondScan.OpenFile(args[1]);
			        iv = SecondScan.TrimBytes(iv, BlockSize);
			        cb = SecondScan.JoitBytes(iv, cb);
			        
			        DoFourth = true;
			        int depth=30;
			        cb = SecondScan.TrimBytes(cb, 1+depth*BlockSize);
					lKey = BruteForce.Crack(lKey, cb, new WordDictionary(), BlockSize);
					
					System.out.println("Bruteforce Done");
					System.out.println("Confidence Level: " + BruteForce.confidence);
				}
				else{
					System.out.println("Starting Phase 3 - Too many/few missing values for Bruteforce. Assigning values by order.");
					if (lKey.CountMissingValues()==1)
						DoFourth = true;
					
					for (i=0; i<52; i++){
						if (lKey.Plain2Cipher[i]==0){
							for (j=0; j<52; j++){
								if (lKey.Cipher2Plain[j]==0){
									lKey.SetValue(lKey.TranslateIndexToChar(i), lKey.TranslateIndexToChar(j), "plain");
									lKey.SetValue(lKey.TranslateIndexToChar(j), lKey.TranslateIndexToChar(i), "cipher");
									break;
								}
							}
						}
					}
				}
				
				System.out.println("Phase 3 Done");
				System.out.println(lKey.CountMissingValues() + " missing values");
			}
		}
		
		if (DoFourth){
			System.out.println("Starting Phase 4 - Fixing worngly capitalized letters");
			System.out.println("Decrypting");
			st.Transform(args[1],args[0], lKey, BlockSize);
			lKey = FourthScan.Scan(lKey, args[0], args[1], BlockSize);
			System.out.println("Phase 4 Done: " + FourthScan.counter + " pairs fixed");
		}
		
		System.out.println("Done Cracking!!!");
		System.out.println("Writing key to file " + args[1] + "_key.txt");
		FileWriter fwTemp = new FileWriter(args[1] + "_key.txt");
        PrintWriter pwTemp = new PrintWriter(fwTemp);
        	pwTemp.write(lKey.LargeKeyToString());
        fwTemp.close();
        pwTemp.close();
        
        long stopTime = System.currentTimeMillis();
        System.out.println("Elapsed time was " + ((double)(stopTime - startTime))/((double)1000) + " seconds.");
        
        
        
        File file = new File("Tranform.txt");
		file.delete();
	}
}